package stz.flash.option.strobe;

import java.util.Hashtable;
import java.util.Vector;

import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.FieldChangeListener;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.Keypad;
import net.rim.device.api.ui.Ui;
import net.rim.device.api.ui.XYEdges;
import net.rim.device.api.ui.component.EditField;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.ObjectChoiceField;
import net.rim.device.api.ui.container.HorizontalFieldManager;
import net.rim.device.api.ui.container.VerticalFieldManager;
import net.rim.device.api.ui.decor.Background;
import net.rim.device.api.ui.decor.BackgroundFactory;
import net.rim.device.api.ui.decor.Border;
import net.rim.device.api.ui.decor.BorderFactory;
import stz.flash.main.strobe.field.StrobeControlBar;
import stz.flash.option.OptionLabel;
import stz.flash.string.OptionString;
import blackberry.util.field.DjFieldInfo;


public final class StrobeTimeIntervalManager extends VerticalFieldManager {
	
	public static final int TIME_LABEL_AND_EDIT_FIELD_FONT_SIZE_px = Ui.convertSize(
			OptionLabel.INFO_LABEL_FONT_HEIGHT_pt + 1, Ui.UNITS_pt, Ui.UNITS_px);
	
	public static final int UNIT_LABEL_FONT_SIZE_px = 
			Ui.convertSize(2, Ui.UNITS_mm, Ui.UNITS_px);
	
	public static final int TIME_INTERVAL_MINIMUM = 1;
	public static final int TIME_INTERVAL_MAXMUM = 99999;
	
	private LabelAndEditFieldManager timeFieldManager = new LabelAndEditFieldManager(); 
	private TimeIntervalChoiceField choiceField = new TimeIntervalChoiceField(OptionString.TIME_INTERVAL_CHOICE_FIELD_ITEM_LABEL, timeFieldManager);

	public static final Integer TIME_INTERVAL_INTEGER1 = new Integer(60);
	public static final Integer TIME_INTERVAL_INTEGER2 = new Integer(80);
	public static final Integer TIME_INTERVAL_INTEGER3 = new Integer(100);
	public static final Integer TIME_INTERVAL_INTEGER4 = new Integer(120);
	public static final Integer TIME_INTERVAL_INTEGER5 = new Integer(140);
	public static final Integer TIME_INTERVAL_INTEGER6 = new Integer(160);
	public static final Integer TIME_INTERVAL_INTEGER7 = new Integer(180);
	public static final Integer TIME_INTERVAL_INTEGER8 = new Integer(200);
	public static final Integer TIME_INTERVAL_INTEGER9 = new Integer(220);
	public static final Integer TIME_INTERVAL_INTEGER10 = new Integer(240);

	private static final StrobeTimeIntervalManager instance = new StrobeTimeIntervalManager();
	
	private StrobeTimeIntervalManager() {
		setBorder(BorderFactory.createSimpleBorder(
				new XYEdges(0, 1, 0, 1),
				Border.STYLE_TRANSPARENT));
	
		add(choiceField);
		add(timeFieldManager);
		setPadding(0, 0, DjFieldInfo.DEFAULT_PADDING_SIZE_px, 0);
	}
	
	public static StrobeTimeIntervalManager getIns(){
		return instance;
	}
	
	
	public void setMainIndex(int index){
		TimeIntervalChoiceField.setMainIndex(index);
	}
	public void increaseMainIndex(){
		choiceField.increaseMainIndex();
	}
	public void decreaseMainIndex(){
		choiceField.decreaseMainIndex();
	}
	
	public void updateTimeInterval() {
		TimeIntervalChoiceField.updateTimeInterval();
	}
	
	
	public void setSelectedIndex(int arg0) {
		choiceField.setSelectedIndex(arg0);
	}
	public void fieldChanged(Field field, int i) {
		choiceField.fieldChanged(field, i);
	}
	public int vectorSize() {
		return choiceField.vectorSize();
	}

	
	protected void onFocus(int i) {
		BackgroundChanger.changeToFocusBackground(this);
		super.onFocus(i);
	}
	
	protected void onUnfocus() {
		BackgroundChanger.changeToNullBackground(this);
		super.onUnfocus();
	}
}


class TimeIntervalChoiceField extends ObjectChoiceField implements FieldChangeListener {

	private static final int CONTEXT_VISIBILITY_CHANGE = 1;

	private static final Vector choicesVector = new Vector(); 
	{
		choicesVector.addElement(OptionString.TIME_INTERVAL_CHOICE_FIELD_CHOICE1); 
		choicesVector.addElement(OptionString.TIME_INTERVAL_CHOICE_FIELD_CHOICE2);
		choicesVector.addElement(OptionString.TIME_INTERVAL_CHOICE_FIELD_CHOICE3); 
		choicesVector.addElement(OptionString.TIME_INTERVAL_CHOICE_FIELD_CHOICE4); 
		choicesVector.addElement(OptionString.TIME_INTERVAL_CHOICE_FIELD_CHOICE5); 
		choicesVector.addElement(OptionString.TIME_INTERVAL_CHOICE_FIELD_CHOICE6); 
		choicesVector.addElement(OptionString.TIME_INTERVAL_CHOICE_FIELD_CHOICE7); 
		choicesVector.addElement(OptionString.TIME_INTERVAL_CHOICE_FIELD_CHOICE8); 
		choicesVector.addElement(OptionString.TIME_INTERVAL_CHOICE_FIELD_CHOICE9); 
		choicesVector.addElement(OptionString.TIME_INTERVAL_CHOICE_FIELD_CHOICE10);
		choicesVector.addElement(OptionString.TIME_INTERVAL_CHOICE_FIELD_CUSTOM);
	};
	
	private static Hashtable table = new Hashtable(); 
	{
		table.put(choicesVector.elementAt(0), StrobeTimeIntervalManager.TIME_INTERVAL_INTEGER1);
		table.put(choicesVector.elementAt(1), StrobeTimeIntervalManager.TIME_INTERVAL_INTEGER2);
		table.put(choicesVector.elementAt(2), StrobeTimeIntervalManager.TIME_INTERVAL_INTEGER3);
		table.put(choicesVector.elementAt(3), StrobeTimeIntervalManager.TIME_INTERVAL_INTEGER4);
		table.put(choicesVector.elementAt(4), StrobeTimeIntervalManager.TIME_INTERVAL_INTEGER5);
		table.put(choicesVector.elementAt(5), StrobeTimeIntervalManager.TIME_INTERVAL_INTEGER6);
		table.put(choicesVector.elementAt(6), StrobeTimeIntervalManager.TIME_INTERVAL_INTEGER7);
		table.put(choicesVector.elementAt(7), StrobeTimeIntervalManager.TIME_INTERVAL_INTEGER8);
		table.put(choicesVector.elementAt(8), StrobeTimeIntervalManager.TIME_INTERVAL_INTEGER9);
		table.put(choicesVector.elementAt(9), StrobeTimeIntervalManager.TIME_INTERVAL_INTEGER10);
		//Custom은 업데이트 해줘야함
		table.put(choicesVector.elementAt(10), StrobeOption.getIns().getCustomTimeInterval());
	}
	
	private LabelAndEditFieldManager timeFieldManager;
	
	public TimeIntervalChoiceField(String label, LabelAndEditFieldManager timeFieldManager) {
		super(label, null);
		this.timeFieldManager = timeFieldManager; 
		setChoices(extractChoices());
		initSelection();
		setChangeListener(this);
	}
	private String[] extractChoices() {
		String[] choices = new String[choicesVector.size()];
		for (int i = 0; i < choicesVector.size(); i++) {
			choices[i] = (String) choicesVector.elementAt(i);
		}
		return choices;
	}
	private void initSelection(){
		setSelectedIndex(getMainIndex());
	}


	public void increaseMainIndex(){
		setMainIndex(checkLimit(getMainIndex() + 1));
	}
	public void decreaseMainIndex(){
		setMainIndex(checkLimit(getMainIndex() - 1));
	}
	private static int checkLimit(int index){
		if (index > table.size() - 1) 
			return table.size() - 1;
		else if (index < 0)
			return 0;
		return index;
	}
	
	
	private static int getMainIndex(){
		return StrobeOption.getIns().getTimeIntervalMainIndex();
	}
	public static void setMainIndex(int index) {
		StrobeOption.getIns().setTimeIntervalMainIndex(index);
	}
	public static void updateTimeInterval() {
		StrobeOption.getIns().setTimeInterval((Integer) table.get(
				choicesVector.elementAt(getMainIndex())));
	}
	
	
	public int vectorSize() {
		return choicesVector.size();
	}
	
	protected void onVisibilityChange(boolean visible) {
		if (visible)
			fieldChanged(null, CONTEXT_VISIBILITY_CHANGE);
		super.onVisibilityChange(visible);
	}
	
	
	public static void updateCustomTimeIntervalInVector(){
		table.remove(OptionString.TIME_INTERVAL_CHOICE_FIELD_CUSTOM);
		table.put(OptionString.TIME_INTERVAL_CHOICE_FIELD_CUSTOM, 
				StrobeOption.getIns().getCustomTimeInterval());
	}
	
	
	public void fieldChanged(Field field, int i) {
		
		if (i == PROGRAMMATIC || i == 0)
			return;
			
		if (i == CONTEXT_CHANGE_OPTION) {
			setMainIndex(getSelectedIndex());
			StrobeControlBar.getIns().moveWithIndex(getMainIndex(), false);
		
		} else if (i == CONTEXT_VISIBILITY_CHANGE){
			
			setSelectedIndex(getMainIndex());
			
		}
		
		if (getChoice(getSelectedIndex()) == OptionString.TIME_INTERVAL_CHOICE_FIELD_CUSTOM) 
			timeFieldManager.enableTimeFields();
		else
			timeFieldManager.disableTimeFields();
		
		setOptionAndTextField();
	}
	private void setOptionAndTextField() {
		Integer timeInterval = (Integer) table.get((String) getChoice(getSelectedIndex()));
		StrobeOption.getIns().setTimeInterval(timeInterval);
		timeFieldManager.setEditField(timeInterval);
	}
}


final class LabelAndEditFieldManager extends VerticalFieldManager {

	public static final int ENABLE_COLOR_OF_FONT = Color.BLACK; 
	public static final int DISABLE_COLOR_OF_FONT = Color.GRAY; 
	
	private ColorChangeLabel labelField = new ColorChangeLabel(
			OptionString.TIME_INTERVAL_EDIT_FIELD);
	
	public static final TimeIntervalEditField editField = new TimeIntervalEditField();
	
	private ColorChangeLabel units = new ColorChangeLabel(
			OptionString.TIME_INTERVAL_UNIT_LABEL_MESSAGE, 
			Field.FIELD_BOTTOM);
	
	public LabelAndEditFieldManager() {
		super();
		HorizontalFieldManager hor = new HorizontalFieldManager();
		hor.add(labelField);
		hor.add(editField);
		hor.add(units);
		add(hor);
		setFont();
	}
	
	private void setFont(){
		Font lableAndEditFont = getFont().derive(Font.PLAIN,
				StrobeTimeIntervalManager.TIME_LABEL_AND_EDIT_FIELD_FONT_SIZE_px);
		labelField.setFont(lableAndEditFont);
		editField.setFont(lableAndEditFont);
		units.setFont(getFont().derive(Font.PLAIN, StrobeTimeIntervalManager.UNIT_LABEL_FONT_SIZE_px));
	}
	
	public void setEditField(Integer time){
		try {
			if (editField.getPreferredWidth() == 0) {
				editField.setText(String.valueOf(time.intValue()));
				sublayout(getPreferredWidth(), getPreferredHeight());
			} else {
				
				editField.setText(String.valueOf(time.intValue()));
			}
		} catch (IllegalArgumentException e) { 
		}
	}

	public void enableTimeFields(){
		TimeIntervalEditField.setFocusable(true);
		TimeIntervalFontColor.setEnableColor();
		BackgroundChanger.changeToWhiteBackground(editField);
	}

	public void disableTimeFields(){
		TimeIntervalEditField.setFocusable(false);
		TimeIntervalFontColor.setDisableColor();
		BackgroundChanger.changeToNullBackground(editField);
	}
	
	class ColorChangeLabel extends LabelField {
		
		public ColorChangeLabel(Object label) {
			super(label);
		}

		public ColorChangeLabel(Object label, long style) {
			super(label, style);
		}

		protected void paint(Graphics g) {
			g.setColor(TimeIntervalFontColor.getFontColor());
			super.paint(g);
		}
	}
}

class TimeIntervalEditField extends EditField implements FieldChangeListener {
	
	private static final int MAX_NUM_CHARS = 5;
	
	private static boolean focusable = true;
	
	public TimeIntervalEditField() {
		super("", "", MAX_NUM_CHARS, EditField.FILTER_NUMERIC);
		setChangeListener(this);
	}
	
	public static void setFocusable(boolean focusable) {
		TimeIntervalEditField.focusable = focusable;
	}
	
	public void fieldChanged(Field field, int i) {
		if (PROGRAMMATIC == i)
			return;
		
		try {
			int timeInterval = Integer.parseInt(getText());
			timeInterval = checkLimitValue(timeInterval);
			setTimeInterval(new Integer(timeInterval));
		} catch (NumberFormatException e) { 
		}
		
	}
	
	private int checkLimitValue(int time) {
		if (time < StrobeTimeIntervalManager.TIME_INTERVAL_MINIMUM)
			time = StrobeTimeIntervalManager.TIME_INTERVAL_MINIMUM;
		else if (time > StrobeTimeIntervalManager.TIME_INTERVAL_MAXMUM)
			time = StrobeTimeIntervalManager.TIME_INTERVAL_MAXMUM;
		return time;
	}
	
	private void setTimeInterval(Integer time) {
		StrobeOption.getIns().setTimeInterval(time);
		StrobeOption.getIns().setCustomTimeInterval(time);
		TimeIntervalChoiceField.updateCustomTimeIntervalInVector();
	}
	
	protected void onUnfocus() {
		super.onUnfocus();
		updateCustomField();
	}
	
	protected boolean keyDown(int i, int j) {
		if (Keypad.key(i) == Keypad.KEY_ENTER)
			updateCustomField();
		return super.keyDown(i, j);
	}
	
	private void updateCustomField() {
		setText(String.valueOf(StrobeOption.getIns().getCustomTimeInterval()));
	}
	
	protected void layout(int i, int j) {
		super.layout(getPreferredWidth(), j);
	}
	
	public int getPreferredWidth() {
		return getFont().getAdvance(getText());
	}
	
	public boolean isFocusable() {
		return focusable;
	}
	
	protected void paint(Graphics g) {
		g.setColor(TimeIntervalFontColor.getFontColor());
		super.paint(g);
	}
	
	public void setText(String text) throws IllegalArgumentException {
		super.setText(text);
	}
	
	protected void displayFieldFullMessage() {
	}
}



final class TimeIntervalFontColor {
	
	private static int fontColor;
	
	public static int getFontColor() {
		return fontColor;
	}

	public static void setEnableColor() {
		TimeIntervalFontColor.fontColor = LabelAndEditFieldManager.ENABLE_COLOR_OF_FONT;
	}
	
	public static void setDisableColor() {
		TimeIntervalFontColor.fontColor = LabelAndEditFieldManager.DISABLE_COLOR_OF_FONT;
	}
}


final class BackgroundChanger {
	
	private static Background whiteBackground = BackgroundFactory.createSolidBackground(Color.WHITE);
	
	public static void changeToFocusBackground(Field field) {
		field.setBackground(DjFieldInfo.DEFAULT_FOCUSED_BACKGROUND);
	}
	
	public static void changeToNullBackground(Field field) {
		field.setBackground(null);
	}
	
	public static void changeToWhiteBackground(Field field) {
		field.setBackground(whiteBackground);
	}
}

